<template>
  <div class="relation-page">
    <div class="view-head">
      <div class="title">边属性</div>
      <div>
        <el-button class="btn" size="mini" type="primary" @click="save"
          >保存</el-button
        >
        <el-button class="btn" size="mini" type="primary" @click="goBack"
          >返回</el-button
        >
      </div>
    </div>
    <section class="entity-msg">
      <div class="header">
        <div class="msg">边信息</div>
      </div>
      <el-form
        ref="form"
        :model="form"
        label-width="86px"
        class="form-content"
        label-position="left"
      >
        <el-form-item label="头实体：" prop="type">
          <img
            :src="relationDetail.sourceEntityName"
            v-if="relationDetail.sourceEntityStatus == 1"
            style="width: 80px"
          />
          <div class="content-item one-row-text" v-else>
            {{ relationDetail.sourceEntityName }}
          </div>
        </el-form-item>
        <el-form-item label="尾实体：" prop="type">
          <img
            :src="relationDetail.tailEntityName"
            v-if="relationDetail.tailEntityStatus == 1"
            style="width: 80px"
          />
          <div class="content-item one-row-text" v-else>
            {{ relationDetail.tailEntityName }}
          </div>
        </el-form-item>
        <el-form-item label="关系名称：" prop="type">
          <div class="content-item one-row-text">
            {{ relationDetail.relationName }}
          </div>
        </el-form-item>
      </el-form>
    </section>
    <section class="property-msg">
      <div class="msg" style="margin-bottom: 18px">属性信息</div>
      <el-form
        ref="elForm"
        class="content"
        :model="item"
        v-for="(item, index) in listData"
        :key="index"
      >
        <el-form-item
          label-width="0"
          prop="propertyName"
          :rules="[
            {
              required: true,
              message: '请输入属性名',
              trigger: ['change', 'blur'],
            },
          ]"
        >
          <el-input
            class="content-value"
            v-model="item.propertyName"
            :disabled="!canEdit(item)"
            placeholder="请输入属性名"
            style="margin-right: 10px"
            @input="(val) => changePropVal(val, index)"
          ></el-input>
          <span
            v-show="canEdit(item)"
            style="margin-right: 20px; cursor: pointer; color: #6f8def"
            @click="bindOntologyProp(index)"
            >去选择</span
          >
        </el-form-item>
        <el-form-item
          style="margin-right: 20px"
          label-width="0"
          :prop="`listData.${index}.propertyType`"
          v-if="item.editIsProperty"
          :rules="{
            required: true,
            validator: validateType,
            trigger: 'change',
          }"
        >
          <el-select
            v-model="item.propertyType"
            class="content-value"
            @change="(val) => changePropertyType(val, index)"
          >
            <el-option
              v-for="obj in propertyTypeOptions"
              :key="obj.key"
              :value="obj.key"
              :label="obj.label"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item
          label-width="0"
          :prop="`listData.${index}.propertyValue`"
          class="inline-value"
          :rules="[
            {
              required: true,
              validator: validatePass,
              trigger: ['change', 'blur'],
            },
          ]"
        >
          <!-- 枚举值类型 -->
          <el-select
            class="content-value"
            v-model="item.propertyValue"
            :disabled="!canEdit(item)"
            v-if="item.propertyBind == 'enum'"
          >
            <el-option
              v-for="(eItem, index) in item.enumNames"
              :key="index"
              :label="eItem"
              :value="eItem"
            ></el-option>
          </el-select>
          <!-- 非枚举值 -->
          <template v-else>
            <!-- 字符 数字类型 坐标 或没有设置类型 都是input输入框 -->
            <el-input
              class="content-value"
              v-if="
                item.propertyType == 'text' ||
                item.propertyType == 'int' ||
                item.propertyType == 'float' ||
                !item.propertyType
              "
              type="input"
              :disabled="!canEdit(item)"
              v-model.trim="item.propertyValue"
            ></el-input>
            <!-- 日期格式 -->
            <el-date-picker
              v-if="item.propertyType == 'date'"
              class="content-value"
              :picker-options="pickerOptions(item.startRange, item.endRange)"
              :disabled="!canEdit(item)"
              v-model="item.propertyValue"
              align="right"
              type="date"
              placeholder="选择日期"
              value-format="yyyy-MM-dd"
              :clearable="false"
            >
            </el-date-picker>
            <!-- 时间格式 -->
            <el-date-picker
              v-if="item.propertyType == 'datetime'"
              class="content-value"
              :picker-options="pickerOptions(item.startRange, item.endRange)"
              :disabled="!canEdit(item)"
              v-model="item.propertyValue"
              type="datetime"
              placeholder="选择日期时间"
              value-format="yyyy-MM-dd HH:mm:ss"
              :clearable="false"
            >
            </el-date-picker>
            <!-- 坐标 -->
            <span v-if="item.propertyType == 'coordinate'"
              >经度：<el-input
                class="small-content"
                style="width: 100px; margin-right: 10px"
                v-model="item.coordX"
              ></el-input
              >维度：<el-input
                class="small-content"
                style="width: 100px"
                v-model="item.coordY"
              ></el-input
            ></span>
            <!-- 图片和文件 -->
            <span v-if="item.propertyType == 'file'">{{ item.fileName }}</span>
            <span v-if="item.propertyType == 'image'"
              ><img :src="item.propertyValue" style="width: 140px"
            /></span>
            <el-upload
              :disabled="!canEdit(item)"
              v-if="item.propertyType == 'image' || item.propertyType == 'file'"
              class="upload-demo"
              style="margin-left: 20px"
              :before-upload="
                (file) => {
                  beforeUpload(file, item);
                }
              "
              :show-file-list="false"
              action=""
            >
              <el-button size="small" type="primary">上传</el-button>
            </el-upload>

            <!-- 数组类型 用多选 -->
            <template v-if="item.propertyType == 'array'">
              <el-select
                :disabled="!canEdit(item)"
                v-model="item.propertyValue"
                multiple
                filterable
                allow-create
                default-first-option
                class="hide-select content-value"
                popper-class="hide-always"
              ></el-select>
              <el-tooltip content="当前属性为数组类型，输入一项后按回车继续">
                <i
                  class="el-icon-warning"
                  style="margin-left: 5px; font-size: 16px"
                ></i>
              </el-tooltip>
            </template>
          </template>
        </el-form-item>
        <i
          v-show="canEdit(item)"
          class="el-icon-close content-icon"
          @click="deleteProperty(item, index)"
        ></i>
      </el-form>
      <el-button
        icon="el-icon-plus"
        class="add-btn"
        @click="addProperty"
        style="margin-bottom: 18px"
        >添加</el-button
      >

      <!-- <div class="header">
        <div class="msg">属性信息</div>
      </div>
      <div class="content" v-for="(item, index) in listData" :key="index">
        <el-input
          v-model="item.propertyName"
          placeholder="属性名"
          class="content-value"
        ></el-input>
        <el-input
          v-model="item.propertyValue"
          placeholder="输入属性值"
          class="content-value"
        ></el-input>
        <i
          class="el-icon-close content-icon"
          @click="deleteProperty(item, index)"
        ></i>
      </div> -->
    </section>
    <SelectRelationProp
      ref="selectOntologyPropRef"
      @select-property="selectPropertyVal"
    ></SelectRelationProp>
  </div>
</template>

<script>
import { EventBus } from "@/views/server/knowledge-management/eventBus";
import SelectRelationProp from "@/components/knowledgeManage/SelectRelationProp.vue";

export default {
  components: {
    SelectRelationProp,
  },
  data() {
    return {
      form: {},
      listData: [],
      relationDetail: {
        sourceEntityName: "",
        sourceEntityStatus: "",
        tailEntityName: "",
        tailEntityStatus: "",
        relationName: "",
      },
      isEditName: false,
      propertyTypeOptions: [
        { key: "text", label: "字符串" },
        { key: "int", label: "整数值" },
        { key: "float", label: "浮点值" },
        { key: "date", label: "日期" },
        { key: "datetime", label: "日期时间" },
        { key: "coordinate", label: "坐标" },
        { key: "array", label: "数组" },
        { key: "image", label: "图片" },
        { key: "file", label: "文件" },
      ],
      ontologyId: "",
      startPosition: "",
      endPosition: "",
      relationName: "",
      relationProperty: [],
      selectKnowledge: "", // 选中的图谱的数据
      relationCon: [],
      operaPropIdx: null, // 归属本体类关系id
      relationId: null,
      ontologySpoId: null,
    };
  },
  async created() {
    EventBus.$on("selectKnowledge", (val) => {
      this.selectKnowledge = val;
    });
    await this.listRelationProperty();
  },
  beforeDestroy() {
    EventBus.$off("selectKnowledge");
  },
  methods: {
    // 属性值类型
    validateType(rule, value, callback) {
      const foundNumbers = findNumbers(rule.field);
      let index = foundNumbers[0];
      if (this.listData[index].editIsProperty && !value) {
        callback(new Error("属性值类型不能为空"));
      } else {
        // 校验通过
        callback();
      }
    },
    async listRelationProperty() {
      const params = {
        kgEntityRelationSpoId: this.$route.query.id,
      };
      let res = await this.$axios.get(
        this.$api.knowledgeMap.getRelationPropertyDetail,
        {
          params,
        }
      );
      const { code, data, msg } = res.data;
      if (code == 200) {
        this.relationId = data.relationId;
        this.ontologySpoId = data.ontologySpoId;
        this.listData = data.respPropertyVoList.map((es) => {
          if (es.propertyType === "array") {
            try {
              es.propertyValue = JSON.parse(es.propertyValue);
            } catch {
              es.propertyValue = [];
            }
          }
          if (es.propertyType === "coordinate") {
            es.coordX = es.propertyValue.split(",")[0];
            es.coordY = es.propertyValue.split(",")[1];
          }
          if (es.isPrivate == "0") {
            es.editIsProperty = true;
          }
          return es;
        });
        Object.assign(this.relationDetail, data);
      } else {
        this.$message.error(msg);
      }
    },
    async getPropertyByRelationId(id) {
      const params = {
        kgEntityRelationSpoId: this.$route.query.id,
      };
      let res = await this.$axios.get(
        this.$api.knowledgeMap.getPropertyByRelationId,
        {
          params,
        }
      );
      const { data, code, msg } = res.data;
      if (code === 200) {
        this.relationCon = data;
      } else {
        this.$message.warning(msg);
      }
    },
    async save() {
      // this.listData.forEach((item) => {
      //   let index = this.relationCon.findIndex((ele, index) => {
      //     return ele.propertyName === item.propertyName;
      //   });
      //   if (index > -1) {
      //     (item.propertyId = this.relationCon[index].propertyId),
      //       (item.propertyType = this.relationCon[index].propertyType);
      //   } else {
      //     (item.propertyId = ""), (item.propertyType = "");
      //   }
      // });
      this.listData = this.listData.map((item) => {
        if (
          Object.prototype.toString.call(item.propertyValue) ===
          "[object Array]"
        ) {
          item.propertyValue = JSON.stringify(item.propertyValue);
        }
        if (item.propertyType === "coordinate") {
          item.propertyValue = item.coordX + "," + item.coordY;
        }
        if (!item.editIsProperty) {
          item.propertyId = "";
        }
        return item;
      });
      if (
        this.listData.some((item) => {
          return item.propertyName == "" || item.propertyValue == "";
        })
      ) {
        this.$message.warning("请填写完整信息！");
        return false;
      }

      let params = {
        kgEntityRelationSpoId: this.$route.query.id,
        ontologySpoId: this.ontologySpoId,
        reqPropertyVoList: this.listData,
      };

      let res = await this.$axios.post(
        this.$api.knowledgeMap.addRelationProperty,
        params
      );
      const { data, code, msg } = res.data;
      if (code === 200) {
        this.isView = true;
        this.$message.success(msg);
        this.listRelationProperty();
      } else {
        this.$message.error(msg);
      }
    },
    deleteProperty(item, index) {
      this.$confirm("确认删除该边属性？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          // deleteRelationProperty
          this.$axios.get(this.$api.knowledgeMap.deleteRelationProperty, {
            params: {
              id: item.propertyId,
            },
          });
          this.listData.splice(index, 1);
          this.$message.success("删除成功");
        })
        .catch(() => {
          this.$message.info("已取消");
        });
    },
    addProperty() {
      let obj = {
        propertyName: "",
        propertyValue: "",
        newProperty: true,
        startRange: "",
        endRange: "",
        coordX: "", //经度
        coordY: "", //维度
        propertyType: "",
      };
      this.listData.push(obj);
    },
    // querySearch(queryString, cb) {
    //   var restaurants = this.relationCon;
    //   clearTimeout(timer);
    //   let timer = setTimeout(() => {
    //     var results = queryString ?
    //       restaurants.filter(this.createFilter(queryString)) :
    //       restaurants;
    //     // 调用 callback 返回建议列表的数据
    //     cb(results);
    //   }, 300 * Math.random());
    // },
    // handleSelect() {},
    // createFilter(queryString) {
    //   return (restaurant) => {
    //     return (
    //       restaurant.propertyName
    //       .toLowerCase()
    //       .indexOf(queryString.toLowerCase()) === 0
    //     );
    //   };
    // },
    goBack() {
      this.$router.go(-1);
    },
    // 修改属性名 应取消属性值组件的绑定约束
    changePropVal(val, index) {
      this.listData[index].editIsProperty = true;
      this.listData[index].propertyValue = "";
      let curProp = this.listData[index];
      if (curProp.propertyType) {
        for (let k in curProp) {
          if (!["propertyName", "propertyValue"].includes(k)) {
            delete curProp[k];
          }
        }
      }
    },
    bindOntologyProp(idx) {
      this.operaPropIdx = idx;
      this.$refs.selectOntologyPropRef.show(this.relationId);
    },
    validatePass(rule, value, callback) {
      function findNumbers(str) {
        // 使用正则表达式匹配所有的数字
        const numbers = str.match(/\d+/g);
        return numbers || []; // 如果没有匹配到数字，则返回空数组
      }
      const foundNumbers = findNumbers(rule.field);
      let index = foundNumbers[0];
      let property = this.listData[index];

      if (property.propertyType && property.propertyType == "coordinate") {
        // 属性值类型为坐标
        if (!property.coordX || !property.coordY) {
          callback(new Error("属性值不能为空"));
        } else {
          callback();
        }
      } else {
        if (value == "" || value == null) {
          callback(new Error("属性值不能为空"));
        } else {
          // const foundNumbers = findNumbers(rule.field);
          // let index = foundNumbers[0];
          // let property = this.listData[index];
          this.listData.forEach((property) => {
            if (property.propertyType) {
              if (property.propertyBind == "no_bind") {
                callback();
              }
              if (property.propertyBind == "enum") {
                callback();
              }
              if (property.propertyBind == "range") {
                // 数字范围值 需要转换为number比较
                if (["int", "float"].includes(property.propertyType)) {
                  if (
                    parseFloat(value) < parseFloat(property.startRange) ||
                    parseFloat(value) > parseFloat(property.endRange)
                  ) {
                    callback(
                      new Error(
                        `属性值应在${property.startRange}~${property.endRange}之间`
                      )
                    );
                  } else {
                    callback();
                  }
                } else {
                  if (
                    value < property.startRange ||
                    value > property.endRange
                  ) {
                    callback(
                      new Error(
                        `属性值应在${property.startRange}~${property.endRange}之间`
                      )
                    );
                  } else {
                    callback();
                  }
                }
              }
            } else {
              callback();
            }
          });
        }
      }
    },
    pickerOptions(startRange, endRange) {
      return {
        disabledDate: (time) => {
          if (endRange && endRange != "" && startRange && startRange != "") {
            return (
              time.getTime() > new Date(endRange).getTime() ||
              time.getTime() < new Date(startRange).getTime()
            );
          }
        },
      };
    },
    changePropertyType(val, index) {
      let property = this.listData[index];
      if (["coordinate", "array", "image", "file"].includes(val)) {
        property.propertyBind = "no_bind";
        property.propertyBindDisabled = true;
      } else {
        property.propertyBindDisabled = false;
      }
      if (["date", "datetime", "int", "float"].includes(val)) {
        property.startRange = "";
        property.endRange = "";
        property.propertyValue = "";
      }
      // 切换为字符串类型时 如果已经选择了范围约束类型 则重置
      if (val === "text" && property.propertyBind === "range") {
        property.propertyBind = "no_bind";
      }
    },
    beforeUpload(file, item) {
      const formData = new FormData();
      formData.append("file", file);
      formData.append("pathType", item.propertyType);
      this.$axios
        .post(this.$api.knowledgeMap.uploadRelationPropertyFile, formData)
        .then((res) => {
          if (res.status == 200) {
            item.fileName = res.data.fileName;
            item.propertyValue = res.data.fileUrl;
            this.$message.success("上传成功");
            this.$forceUpdate();
          }
        });
    },
    selectPropertyVal(val) {
      Object.assign(this.listData[this.operaPropIdx], val);
      this.listData[this.operaPropIdx].editIsProperty = false;
      this.listData[this.operaPropIdx].propertyValue = "";

      this.$nextTick(() => {
        this.$refs.elForm[this.$refs.elForm.length - 1].clearValidate(
          "propertyValue"
        );
      });
    },
    canEdit(item) {
      if (item.newProperty) {
        return true;
      } else if (item.isPrivate === 1) {
        return false;
      } else {
        return true;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
@import "../../../assets/scss/scroll";

.relation-page {
  font-size: 14px;
  font-family: MicrosoftYaHei;
  color: #333333;
  background: #ffffff;
  border-radius: 4px;
  // height: 98%;

  .view-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 56px;
    border-bottom: 1px solid #dddddd;
    padding: 0 32px;

    .title {
      font-size: 16px;
      font-weight: bold;
    }

    .btn {
      width: 77px;
      height: 32px;
    }
  }

  .form-content {
    .el-form-item {
      height: 32px;
      line-height: 32px;

      /deep/ .el-form-item__label {
        line-height: 32px;
      }

      /deep/ .el-form-item__content {
        line-height: 32px;
      }
    }

    .content-item {
      width: 280px;
      height: 32px;
      background: #f8f8f8;
      border-radius: 2px;
      border: 1px solid #dddddd;
      padding: 0 8px;
      box-sizing: border-box;
    }
  }

  .add-btn {
    width: 76px;
    height: 32px;
    padding: 6px;
    color: #4b71eb;
    margin-top: 22px;
  }

  .content-icon {
    margin-left: 18px;
    margin-top: 4px;
    width: 32px;
    height: 32px;
    line-height: 32px;
    text-align: center;
    border: 1px solid #dddddd;
    box-sizing: border-box;
    border-radius: 2px;
  }

  .entity-msg,
  .property-msg {
    width: 100%;
    padding: 32px 32px 14px 32px;

    .msg {
      border-left: 4px solid #4b71eb;
      padding-left: 6px;
      margin-bottom: 6px;
      font-size: 16px;
      line-height: 16px;
    }

    .header {
      display: flex;
      justify-content: space-between;
      margin-bottom: 20px;
      align-items: flex-end;
    }

    .edit-button {
      color: #4b71eb;
      cursor: context-menu;
    }

    .edit-icon {
      margin-right: 6px;
      font-size: 20px;
    }

    .content {
      // margin-top: 22px;
      display: flex;
      align-items: center;
      margin-bottom: 20px;
      .el-form-item {
        margin-bottom: 0;
      }
      .content-key {
        margin-right: 20px;
      }

      .content-key /deep/.el-input__inner {
        width: 280px;
        height: 32px;
      }

      .content-value {
        width: 280px;
      }

      .content-value /deep/.el-input__inner {
        width: 280px;
        height: 32px;
      }
      .small-content /deep/.el-input__inner {
        width: 100px;
        height: 32px;
      }
    }

    .add-self-property {
      height: 30px;
      margin-top: 16px;
      margin-left: 10px;
      line-height: 6px;
      font-size: 12px;
      width: 100px;
    }
  }

  .property-msg {
    width: 100%;
    padding-top: 0;
    padding-bottom: 0;
  }
}

/deep/ .el-table tbody tr:hover > td {
  background-color: #ffffff !important;
}

.customer-table {
  /deep/ .el-table__row > td {
    /* 去除表格线 */
    border: none;
  }
}

.customer-table {
  background: #ffffff;
  padding: 16px 32px 20px;
  min-height: calc(100% - 136px);

  .table-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .el-table {
    .operation {
      display: flex;
      justify-content: space-around;
      align-items: center;
    }
  }

  /deep/ .cell {
    text-align: center;
  }

  .handle-button {
    margin-right: 10px;
  }
}

.content {
  .form-item-pub {
    height: 32px;
    line-height: 32px;

    /deep/ .el-form-item__label {
      line-height: 32px;
    }

    /deep/ .el-form-item__content {
      line-height: 32px;
    }
  }

  .form-item-remark {
    margin-bottom: 0;
  }

  .upload {
    height: 72px;
  }

  .content-detail {
    height: 138px;

    /deep/ .el-form-item__content {
      height: 100%;
      overflow-y: auto;
      background: #f8f8f8;
      border-radius: 2px;
      border: 1px solid #dddddd;
    }
  }
}
.inline-value {
  :deep(.el-form-item__content) {
    display: flex;
    align-items: center;
    flex-direction: row;
  }
}
</style>
